package elephant.task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import elephant.Container;
import elephant.Lifecycle;
import elephant.util.ObjectPrinter;

/**
 * 
 * @author icecooly
 *
 */
public class TaskManager implements Lifecycle{
	
	private static Logger logger=LoggerFactory.getLogger(TaskManager.class);
	//
	private Map<String, BaseTask> taskMap;
	
	public TaskManager(){
		taskMap=new HashMap<>();
	}
	
	@Override
	public void init() throws Exception {
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" init");
		}
	}

	@Override
	public void start() throws Exception {
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" start");
		}
		taskMap.forEach((id,task)->{
			Container.get().scheduleAtFixedRate(task,task.initialDelay, task.period, task.unit);
		});
	}

	@Override
	public void stop() throws Exception {
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" stop");
		}
	}
	//
	public void registerTask(BaseTask task){
		String id=task.getClass().getSimpleName();
		if(taskMap.containsKey(id)){
			logger.warn("task already register."+id);
			return;
		}
		TaskAnno ta=(task.getClass().getAnnotation(TaskAnno.class));
		if(ta==null){
			throw new IllegalArgumentException("can not find task annotation."+id);
		}
		task.id=task.getClass().getSimpleName();
		task.initialDelay=ta.initialDelay();
		task.period=ta.period();
		task.unit=ta.unit();
		taskMap.put(task.id,task);
		logger.info("registerTask "+task.getId());
	}
	//
	public List<BaseTask>getTasks(){
		return new ArrayList<BaseTask>(taskMap.values());
	}
	//
	public boolean runTask(String id){
		BaseTask task=taskMap.get(id);
		if(task==null){
			return false;
		}
		Container.get().executeThreadWorker(task);
		return true;
	}
	//
	@Override
	public String dump() {
		String format="%-5s: %-20s %-10s %-10s %-10s %-10s %-10s\n";
		ObjectPrinter op=new ObjectPrinter(format);
		op.section(getClass().getSimpleName());
		if(!taskMap.isEmpty()){
			int i=1;
			op.print("#","ID","INITDELAY","PERIOD","UNIT","RUNTIMES","LAST RUN");	
			for(BaseTask task:taskMap.values()){
				op.print(i++,
						task.getId(),
						task.getInitialDelay(),
						task.getPeriod(),
						task.getUnit(),
						task.getRunTimes(),
						task.getLastRunTime());
			};
		}
		return op.toString();
	}

}
